import re

from django import http
from django.conf import settings
from django.contrib.auth import login
from django.core.paginator import EmptyPage, Paginator
from django.db import DatabaseError
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
from django_redis import get_redis_connection

from apps.boke_content.models import Blog
from apps.index.models import Carousel
from apps.oauth.models import OAuthQQUser
from apps.oauth.utils import generate_access_token, check_access_token
from apps.users.models import User
from utils import constants
from utils.response_code import RETCODE
from QQLoginTool.QQtool import OAuthQQ


class QQAuthURLView(View):
    """提供QQ登录页面网址
    https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=xxx&redirect_uri=xxx&state=xxx
    """

    def get(self, request):
        # next表示从哪个页面进入到的登录页面，将来登录成功后，就自动回到那个页面
        next = request.GET.get('next')

        # 获取QQ登录页面网址
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI,
                        state=next)
        login_url = oauth.get_qq_url()

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'login_url': login_url})


class QQAuthUserView(View):
    """用户扫码登录的回调处理"""

    def get(self, request):
        """Oauth2.0认证"""
        # 接收Authorization Code
        code = request.GET.get('code')
        if not code:
            return http.HttpResponseBadRequest('缺少code')

        # 创建工具对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)

        try:
            # 使用code向QQ服务器请求access_token
            access_token = oauth.get_access_token(code)

            # 使用access_token向QQ服务器请求openid
            openid = oauth.get_open_id(access_token)
        except Exception as e:
            return http.HttpResponseServerError('OAuth2.0认证失败')

        try:
            oauth_user = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 如果openid没绑定美多商城用户
            access_token = generate_access_token(openid)
            context = {'access_token': access_token}
            return render(request, 'oauth_callbacks.html', context)
        else:
            # 如果openid已绑定美多商城用户
            # 实现状态保持
            qq_user = oauth_user.user
            login(request, qq_user)

            # 重定向到主页
            # username = request.COOKIES.get('username')
            #
            # page_num = None
            #
            # blog_content = Blog.objects.filter(carousel__isnull=True).order_by('-create_time')
            # blogs = Blog.objects.filter(carousel__isnull=True).order_by('-read_count')[:5]
            # recommends = Blog.objects.filter(carousel__isnull=True, is_recommend=True)
            #
            # paginator = Paginator(blog_content, constants.GOODS_LIST_LIMIT)
            #
            # carousel = Carousel.objects.all()
            #
            # if not page_num:
            #     page_num = 1
            #
            # try:
            #     page_blogs = paginator.page(page_num)
            # except EmptyPage:
            #     return http.HttpResponseNotFound('empty page')
            #
            # total_page = paginator.num_pages
            #
            # data = {
            #     'username': username,
            #     'blogs': blogs,
            #     'page_num': page_num,
            #     'page_blogs': page_blogs,
            #     'total_page': total_page,
            #     'carousels': carousel,
            #     'recommends': recommends
            # }
            # response = render(request, 'index.html', context=data)
            response = http.HttpResponseRedirect('/')

            # 登录时用户名写入到cookie，有效期15天
            response.set_cookie('username', qq_user.username, max_age=3600 * 24 * 15)

            return response

    def post(self, request):
        """美多商城用户绑定到openid"""

        username = request.POST.get('username')
        email = request.POST.get('email')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        img_code = request.POST.get('code')
        uuid = request.POST.get('uuid')
        access_token = request.POST.get('access_token')

        # 判断参数是否齐全
        if not all([username, password, password2, email, img_code, uuid, access_token]):
            return http.JsonResponse({'code_s': RETCODE.NECESSARYPARAMERR, 'errmsg': '参数不足'})

        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            return http.JsonResponse({'code_s': RETCODE.EMAILERR, 'errmsg': '邮箱错误'})
        # 判断用户名是否是5-20个字符
        if not re.match(r'^[a-zA-Z0-9_]{5,20}$', username):
            return http.JsonResponse({'code_s': RETCODE.USERERR, 'errmsg': '请输入5-20位字符的用户名'})
        # 判断密码是否是8-20个数字
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.JsonResponse({'code_s': RETCODE.PWDERR, 'errmsg': '请输入8-20位的密码'})
        # 判断两次密码是否一致
        if password != password2:
            return http.JsonResponse({'code_s': RETCODE.CPWDERR, 'errmsg': '两次密码不一致'})

        redis_conn = get_redis_connection('code')
        image_code_server = redis_conn.get('img_%s' % uuid)
        if image_code_server is None:
            return http.JsonResponse({'code_s': RETCODE.IMAGECODEERR, 'errmsg': '验证码错误'})

        try:
            redis_conn.delete('img_%s' % img_code)
        except Exception as e:
            print(e)

        # 判断openid是否有效：错误提示放在sms_code_errmsg位置
        openid = check_access_token(access_token)
        if not openid:
            return http.JsonResponse({'code_s': RETCODE.DBERR, 'errmsg': '无效的openid'})

        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:

            # 保存注册数据
            try:
                user = User.objects.create_user(username=username, password=password, email=email)
            except User.DoesNotExist:
                return http.JsonResponse({'code_s': RETCODE.DBERR, 'errmsg': '注册失败'})

        else:
            return http.JsonResponse({'code_s': RETCODE.DBERR, 'errmsg': '用户名已存在'})

        try:
            OAuthQQUser.objects.create(openid=openid, user=user)
        except DatabaseError:
            return http.JsonResponse({'code_s': RETCODE.DBERR, 'errmsg': 'qq登陆失败'})

        login(request, user)

        response = http.JsonResponse({'code_s': RETCODE.OK, 'errmsg': '绑定成功'})

        response.set_cookie('username', user.username, 3600 * 24 * 15)

        return response
